#ifndef _MATH_TRIONOMETRY_H_
#define _MATH_TRIONOMETRY_H_

#include"Power.h"

double arcsch(double x);
double arcoth(double x);

double sine(double x){
	double s1 = 1.0/(2.0*3.0);
	double s2 = 1.0/(4.0*5.0);
	double s3 = 1.0/(6.0*7.0);
	double s4 = 1.0/(8.0*9.0);
	double z = x * x;
	return ((((s4*z-1.0)*s3*z+1.0)*s2*z-1.0)*s1*z+1.0)*x;
}

double cosine(double x){
	double c1 = 1.0/(1.0*2.0);
	double c2 = 1.0/(3.0*4.0);
	double c3 = 1.0/(5.0*6.0);
	double c4 = 1.0/(7.0*8.0);
	double z = x * x;
	return (((c4*z-1.0)*c3*z+1.0)*c2*z-1.0)*c1*z+1.0;
}

double tangent(double x){
	return sine(x)/cosine(x);
}

double secant(double x){
	return 1/cosine(x);
}

double cosecant(double x){
	return 1/sine(x);
}

double cotangent(double x){
	return cosine(x)/sine(x);
}

double sineH(double x)
{
	return (exp(2*x)-1)/(2*exp(x));
}

double cosineH(double x)
{
	return (exp(2*x)+1)/(2*exp(x));
}
double tangentH(double x)
{
	double ett2 = exp(2*x);
	return (ett2 - 1) / (ett2 + 1);
}
double cosecontH(double x)
{
	return 1.0/sineH(x);
}
double secontH(double x)
{
	return 1.0/cosineH(x);
}
double cotangentH(double x)
{
	double ett2 = exp(2*x);
	return (ett2 + 1) / (ett2 - 1);
}
double arsinh(double x)
{
	return ln(x+nthRoot(x*x+1,2));
}
double arcosh(double x)
{
	// x >= 1
	if(x < 1)
		return arsinh(1.0/x);
	return ln(x+nthRoot(x*x-1,2));
}
double artanh(double x)
{
	//abs x < 1
	if(abs(x) > 1)
		return arcoth(1.0/x);
	else
		return .5 * ln((1+x)/(1-x));
}
double arcoth(double x)
{
	//abs x > 1
	if(abs(x) < 1)
		return artanh(1.0/x);
	return .5 * ln((1+x)/(1-x));
}
double arsech(double x)
{
	//0 < x <= 1
	if(x > 1)
		return arcsch(1.0/x);
	else
	return ln(1.0/x + nthRoot(1-x*x,2)/x);
}
double arcsch(double x)
{
	//x != 0
	return ln(1.0/x + nthRoot(1+x*x,2)/abs(x));
}

#endif